package com.mall.web.annotation;

import java.lang.reflect.Method;
import java.util.List;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import com.mall.client.user.SessService;
import com.mall.client.user.UserService;
import com.mall.common.util.token.TokenInfo;
import com.mall.common.util.token.TokenUtils;
import com.mall.constant.ReqAttributeKey;
import com.mall.constant.UserConstant;
import com.mall.pojo.Sess;
import com.mall.pojo.User;
import com.mall.web.util.CookieUtil;
import com.mall.web.util.HttpUtil;
import com.mall.web.util.WebUtil;
import com.mall.web.vo.AjaxResult;
import com.mall.web.vo.StatusInfo;

/**
 * UserSecurity注解的AOP实现
 * 
 * @author zhangxianjun
 * @version $Id: SecurityAop.java, v 0.1 2015年6月15日 下午7:52:05 zhangxianjun Exp $
 */
@Aspect
@Component
public class EShopUserSecurityAop {

	private static final Logger log = LoggerFactory.getLogger(EShopUserSecurityAop.class);

	@Autowired
	private UserService userService;

	@Autowired
	private SessService sessService;

	private String URL_USER_LOGIN = "/eshop/user/eshoplogin.htm";//H5登录
	private String URL_USER_PC_LOGIN = "/eshop/user/pcEshopLogin.htm";//pc登录

	@Around("@annotation(com.mall.web.annotation.EShopUserSecurity)")
	public Object doCheck(ProceedingJoinPoint joinPoint) throws Throwable {

		String methodName = joinPoint.getSignature().getName();
		Method method = joinPoint.getTarget().getClass().getMethod(methodName,
				((MethodSignature) joinPoint.getSignature()).getParameterTypes());
		EShopUserSecurity securityAnnotation = method.getAnnotation(EShopUserSecurity.class);

		// 是否必须登录
		boolean mustLogin = securityAnnotation.mustLogin();
		boolean isPc = securityAnnotation.isPc();
		if (isPc) {
			URL_USER_LOGIN = URL_USER_PC_LOGIN;
		}
		// 当前登录用户
		HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getRequest();
		HttpServletResponse response = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
				.getResponse();

		boolean ajaxMethod = false;
		// 如果方法有@ResponseBody注解，说明该方法是ajax方法
		ResponseBody responseBodyAnnotation = method.getAnnotation(ResponseBody.class);
		if (responseBodyAnnotation != null) {
			ajaxMethod = true;
		}

		if (mustLogin) {
			String cookieValue = "";
			String token = request.getParameter(UserConstant.APP_KEY_OPERATE);
			if (StringUtils.isNotBlank(token)) {
				cookieValue = token;
				TokenInfo tokenInfo = TokenUtils.parseToken(token);
				if (tokenInfo == null) {
					if (ajaxMethod) {
						AjaxResult failResult = new AjaxResult();
						failResult.setCode(StatusInfo.REQUEST_NOT_LOGIN);
						failResult.setMessage(StatusInfo.FAILURE_CHECK_TOKEN);
						HttpUtil.ajaxOutput(failResult, response);
						return null;
					}
					response.sendRedirect(URL_USER_LOGIN);
					return null;
				}
				User user = this.userService.getUserByUserId(tokenInfo.getUserId());
				if (user == null || user.getId() == null || user.getId() <= 0) {
					if (ajaxMethod) {
						AjaxResult failResult = new AjaxResult();
						failResult.setCode(StatusInfo.REQUEST_NOT_LOGIN);
						failResult.setMessage(StatusInfo.FAILURE_CHECK_TOKEN);
						HttpUtil.ajaxOutput(failResult, response);
						return null;
					}
					response.sendRedirect(URL_USER_LOGIN);
					return null;
				}
				if (user.getPassword().equals(tokenInfo.getPassword())) {
					WebUtil.setCurrentUserSessionAndCookies(request, response, user);
					return joinPoint.proceed();
				}
				if (ajaxMethod) {
					AjaxResult failResult = new AjaxResult();
					failResult.setCode(StatusInfo.REQUEST_NOT_LOGIN);
					failResult.setMessage(StatusInfo.FAILURE_CHECK_TOKEN);
					HttpUtil.ajaxOutput(failResult, response);
					return null;
				}
				response.sendRedirect(URL_USER_LOGIN);
				return null;
			} else {
				Cookie[] cookies = request.getCookies();// 这样便可以获取一个cookie数组
				if (cookies == null || cookies.length <= 0) {
					if (ajaxMethod) {
						AjaxResult failResult = new AjaxResult();
						failResult.setCode(StatusInfo.REQUEST_NOT_LOGIN);
						failResult.setMessage(StatusInfo.FAILURE_CHECK_TOKEN);
						HttpUtil.ajaxOutput(failResult, response);
						return null;
					} else {
						response.sendRedirect(URL_USER_LOGIN);
						return null;
					}
				}
				cookieValue = CookieUtil.getCookieValue(request, ReqAttributeKey.COOKIE_FOR_USER);
			}

			if (StringUtils.isBlank(cookieValue)) {
				if (ajaxMethod) {
					AjaxResult failResult = new AjaxResult();
					failResult.setCode(StatusInfo.REQUEST_NOT_LOGIN);
					failResult.setMessage(StatusInfo.FAILURE_CHECK_TOKEN);
					HttpUtil.ajaxOutput(failResult, response);
					return null;
				} else {
					response.sendRedirect(URL_USER_LOGIN);
					return null;
				}
			}
			String commonOnlyKey = CookieUtil.getCookieValue(request, ReqAttributeKey.COOKIE_FOR_COMMKEYID);
			if (StringUtils.isBlank(commonOnlyKey)) {
				if (ajaxMethod) {
					AjaxResult failResult = new AjaxResult();
					failResult.setCode(StatusInfo.REQUEST_NOT_LOGIN);
					failResult.setMessage(StatusInfo.FAILURE_CHECK_TOKEN);
					HttpUtil.ajaxOutput(failResult, response);
					return null;
				} else {
					response.sendRedirect(URL_USER_LOGIN);
					return null;
				}
			}
			List<Sess> listSess = sessService.getListBySessionKey(cookieValue, Integer.parseInt(commonOnlyKey));
			if (listSess == null || listSess.isEmpty()) {
				if (ajaxMethod) {
					AjaxResult failResult = new AjaxResult();
					failResult.setCode(StatusInfo.REQUEST_NOT_LOGIN);
					failResult.setMessage(StatusInfo.FAILURE_CHECK_TOKEN);
					HttpUtil.ajaxOutput(failResult, response);
					return null;
				} else {
					response.sendRedirect(URL_USER_LOGIN);
					return null;
				}
			}
			User user = this.userService.getUserByUserId(listSess.get(0).getUid());
			if (user == null) {
				if (ajaxMethod) {
					AjaxResult failResult = new AjaxResult();
					failResult.setCode(StatusInfo.REQUEST_NOT_LOGIN);
					failResult.setMessage(StatusInfo.FAILURE_CHECK_TOKEN);
					HttpUtil.ajaxOutput(failResult, response);
					return null;
				} else {
					response.sendRedirect(URL_USER_LOGIN);
					return null;
				}
			}
			WebUtil.setCurrentUserSessionAndCookies(request, response, user);
		}
		return joinPoint.proceed();
	}
}
